module windump.plugins.outlook2003.outlook2003;

import std.c.windows.windows;

import windump.scanning.detector;
import windump.util;
import windump.registry;
import windump.utf;
import windump.w32api;

const string Outlook2003Key = `Software\Microsoft`  
                `\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\Outlook`;

class Outlook2003Detector : Detector!(Outlook2003Detector, "email-client/outlook2003", "table")
{
    private alias void delegate(string host, string user, string password) EnumProc;

    public this()
    {
    }

    private bool dealAccount(Key k, EnumProc proc)
    {
        assert(!(k is null));
        assert(!(proc is null));

        try
        {
            string host = toUtf8(cast(wchar*)
                    k.getValue("POP3 Server").value_BINARY().ptr);

            string user = toUtf8(cast(wchar*)
                    k.getValue("POP3 User").value_BINARY());

            ubyte[] password = k.getValue("POP3 Password").value_BINARY();
            
			DATA_BLOB indata, outdata;
			indata.cbData = password.length;
			indata.pbData = password.ptr + 1;
			CryptUnprotectData(&indata, null, null, null, null,CRYPTPROTECT_UI_FORBIDDEN, &outdata);
			scope(exit)
				LocalFree(cast(HGLOBAL)outdata.pbData);
			wchar* pstr= cast(wchar*)outdata.pbData;
			proc(host, user, toUtf8(pstr).dup);
        }
        catch(RegistryException e)
        {
            return false;
        }
        return true;
    }

    private void enumAccounts(EnumProc proc)
    {
        assert(!(proc is null));

        Key hkcu = Registry.currentUser;
        scope Key parent = hkcu.openSubkey(Outlook2003Key);
        for(uint x = 0; x < parent.subkeyCount; x++)
        {
            scope auto k1 = parent.openSubkey(x);
            for(uint y = 0; y < k1.subkeyCount; y++)
            {
                scope auto k2 = k1.openSubkey(y);
                
                if(!dealAccount(k2, proc))
                    continue;
            }
        }     
    }

    public override ResultItem[] update()
    {
        ResultItem[] ret;

        void proc(string host, string user, string pwd)
        {
            ResultItem item;
            
            item.provider = name();
            item.host = host;
            item.account = user;
            item.password = pwd;

            ret ~= item;
            
        }

        enumAccounts(&proc);

        return ret;
    }
}
